package com.test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * DependencyDescriptor 类用于描述依赖注入的相关信息。
 * 它支持通过字段、方法参数或构造函数参数来描述依赖项的元数据。
 */
public class DependencyDescriptor {
    private Field field;
    private Parameter methodParameter;
    private Method method;
    private int parameterIndex;
    private Class<?> declaringClass;
    private boolean required;
    private String dependencyName;

    /**
     * 构造函数，基于字段创建依赖描述符。
     *
     * @param field   与依赖项关联的字段对象。
     * @param required 是否为必需依赖项。如果为 true，则表示该依赖项是必须注入的。
     */
    public DependencyDescriptor(Field field, boolean required) {
        this.field = field;
        this.required = required;
        // 获取字段所属的类
        this.declaringClass = field.getDeclaringClass();
    }

    /**
     * 构造函数，基于方法参数创建依赖描述符。
     *
     * @param method         包含依赖项的方法对象。
     * @param parameterIndex 方法中参数的索引位置。
     * @param required       是否为必需依赖项。如果为 true，则表示该依赖项是必须注入的。
     */
    public DependencyDescriptor(Method method, int parameterIndex, boolean required){
        this.method = method;
        this.parameterIndex = parameterIndex;
        // 获取指定索引位置的方法参数
        this.methodParameter = method.getParameters()[parameterIndex];
        // 获取方法所属的类
        this.declaringClass = method.getDeclaringClass();
        this.required = required;
    }

    /**
     * 构造函数，基于方法参数直接创建依赖描述符。
     *
     * @param methodParameter 方法参数对象。
     * @param required        是否为必需依赖项。如果为 true，则表示该依赖项是必须注入的。
     */
    public DependencyDescriptor(Parameter methodParameter, boolean required){
        this.methodParameter = methodParameter;
        this.required = required;
        // 获取方法参数所属的类
        this.declaringClass = methodParameter.getDeclaringExecutable().getDeclaringClass();
    }

    /**
     * 获取依赖项的类型。
     *
     * 如果依赖项是通过字段描述的，则返回字段的类型；
     * 如果依赖项是通过方法参数描述的，则返回方法参数的类型。
     *
     * @return 依赖项的类型。如果既没有字段也没有方法参数，则返回 null。
     */
    public Class<?> getDependencyType() {
        // 如果字段不为空，返回字段的类型
        if (this.field != null) {
            return this.field.getType();
        }
        // 如果方法参数不为空，返回方法参数的类型
        else if (this.methodParameter != null) {
            return this.methodParameter.getType();
        }
        // 如果没有字段和方法参数，返回 null
        return null;
    }
}
